<!--
 * @Author: code DE
 * @Date: 2021-09-17 14:24:37
 * @LastEditTime: 2021-11-10 16:08:35
 * @LastEditors: Please set LastEditors
 * @Description: It's like a gold digger's calendar
 * @FilePath: \calendar\src\components\calendar.vue 
-->  
<template>
    <div class="calendar">
        <div class="calendar-week-head">
            <div class="calendar-week-head-event" @click="handleTop">←</div>
            <div class="calendar-week-head-txt">{{ year + '-' + (month + 1) + '-' + day }}</div>
            <div class="calendar-week-head-event" @click="handleBottom">→</div>
        </div>
        <div class="calendar-week">
            <nav class="calendar-week-item" v-for='v, k in weeks' :key='k'>{{ v }}</nav>
        </div>
        <div class="calendar-day">
            <nav class="calendar-day-item" :class="{'calendar-day-itemgray':item.status !== 1}" v-for="item,key in forDays" :key="'day'+key">
                <div class="calendar-day-item-text" @click="handleSon(item)" :class="{'calendar-day-itemactive':item.active}">
                    {{item.day}}
                </div>
                <nav class="calendar-day-item-hover" v-if="item.list">
                    <nav class="cdih-items">
                        <nav class="cdih-item" v-for="dot,dkey in item.list" :key="'dot'+dkey" :class="{'more':dkey>3}"></nav>
                    </nav>
                    <nav class="cdih-item-show">
                        <nav v-for="hoverItem,hoverKey in item.list" :key="'hoverKey'+hoverKey" @click="activityParams(hoverItem)">{{hoverItem.txt}}</nav>
                    </nav>
                </nav>
            </nav>
        </div>
    </div>
</template>  
<script>
import { reactive, ref, computed, watch, toRefs } from 'vue'
export default {
    name: 'Calendar',
    props: ['activity', 'o'],
    setup(props, { emit, attrs, slots }) {
        const weeks = reactive(['一', '二', '三', '四', '五', '六', '七'])
        const count = ref(7 * 6)
        const oDate = reactive(new Date())
        const year = ref(oDate.getFullYear())                   //获取年  
        const month = ref(oDate.getMonth())                     //获取月
        const day = ref(oDate.getDate())                        //获取当日时间
        const days = reactive([31, 28 + isLeapYear(year.value), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]);       //所有月份的天数,这里条用的一个函数用于计算闰年
        let firstDayLeft = (new Date(year.value, month.value, 1)).getDay();
        const firstDay = ref(firstDayLeft == 0 ? 7 : firstDayLeft);
        const hovers = reactive(props.activity)             //父传子的参数,用于设置任务 活动悬浮效果

        const forDays = computed(() => {
            let start = []             //用于计算 开头
            let monthKey = month.value == 0 ? 0 : month.value - 1;
            for (let i = 1; i <= days[monthKey]; i++) {
                if (i - 1 > days[monthKey] - firstDay.value) {
                    start.push({
                        status: 0,
                        day: i,
                        active:false
                    })
                }
            }
            let center = []             //计算中间 当前月时间
            for (let i = 1; i <= days[month.value]; i++) {
                let itemDay = {
                    status: 1,
                    day: i,
                    active: false
                }
                if (day.value == i) {
                    itemDay.active = true
                } else {
                    itemDay.active = false
                }
                //处理显示的 活动(任务的信息)
                let activityAll = hovers
                activityAll.forEach((yitem, ykey) => {
                    if (yitem.year == year.value) {
                        let monthsAll = yitem.months || [];
                        monthsAll.forEach((mitem, mkey) => {
                            if (mitem.month == (month.value + 1)) {
                                let activityDaysAll = mitem.activity;
                                activityDaysAll.forEach((aitem, akey) => {
                                    if (itemDay.day == aitem.day) {
                                        itemDay.list = aitem.list;
                                    }
                                })
                            }
                        })
                    }
                })
                center.push(itemDay)
            }

            let end = []         //计算尾部
            let end_days = count.value - (start.length + center.length)
            for (let i = 0; i < end_days; i++) {
                end.push({
                    status: 0,
                    day: i + 1,
                    active:false
                })
            }
            return start.concat(center).concat(end)
        })
        watch(month, (n, o) => {        //监听月份
            if (n > 11) {
                year.value = year.value + 1
                month.value = 0
            }
            if (n < 0) {
                year.value = year.value - 1;
                month.value = 11;
            }
            let firstDayLeft = (new Date(year.value, month.value, 1)).getDay();
            firstDay.value = firstDayLeft == 0 ? 7 : firstDayLeft;
            days.value = [31, 28 + isLeapYear(year.value), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
        })
        const handleTop = () => {         //上一个月
            month.value = month.value - 1
        }
        const handleBottom = () => {      //下一个月
            month.value = month.value + 1
        }
        const handleSon = (detail) => {            //日期 子传父
            const params = {
                detail: detail,
                year: year.value,
                month: month.value+1,
            }
            emit('handleParams', params)
        }
        const activityParams = (detail) => {           //活动,单击子传父
            const params = {
                detail: detail,
                day: day.value,
                month: month.value+1,
                year: year.value
            }
            emit('handleActivityParams', params)
        }
        return {
            weeks,
            count,
            oDate,
            year,
            month,
            day,
            days,
            firstDay,

            forDays,

            handleTop, handleBottom, handleSon, activityParams,

            hovers
        }
    }
}

// 计算 闰年
const isLeapYear = (year) => {
    if (((year % 4) == 0) && ((year % 100) != 0) || ((year % 400) == 0)) {
        return 1;
    } else {
        return 0;
    }
} 
</script>

<style scoped>
.calendar {
    width: 100%;
    height: auto;
    box-shadow: 0px 0px 10px #c1bfdd;
    background: white;
}

.calendar-week {
    width: 100%;
    height: 34px;
    line-height: 34px;
    display: flex;
    background-image: linear-gradient(45deg, #97d9e1, #d9afd9);
    font-size: 14px;
    font-weight: 600;
    color: rgba(255, 255, 255, .8);
    user-select: none;
    justify-content: space-around;
}

.calendar-day {
    width: 100%;
    height: auto;
    display: flex;
    flex-wrap: wrap;
    text-align: center;
}

.calendar-day-item {
    height: 34px;
    width: 14%;
    margin: 0px .1%;
}

.calendar-day-item-hover {
    width: 100%;
    height: 10px;
    box-sizing: border-box;
    padding: 0px 10px;
    position: relative;
}

.cdih-items {
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
    max-height: 14px;
    width: 100%;
    overflow: hidden;
}

.cdih-item {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    margin: auto 0px;
    border: 2px solid #585858;
    transform: scale(.5);
}

.more {
    background: #cccc;
}

.cdih-item-show {
    position: absolute;
    display: none;
    left: 50%;
    top: 10px;
    transform: translateX(-50%);
    width: 80px;
    background: white;
    font-size: 12px;
    line-height: 20px;
    padding: 4px 12px;
    box-sizing: border-box;
    z-index: 99;
    box-shadow: 0px 0px 4px #ccc;
}

.cdih-item-show>nav {
    text-align: left;
    width: 100%;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    cursor: pointer;
}

.calendar-day-item-hover:hover>.cdih-item-show {
    display: block;
}

.calendar-day-item-hover:hover .cdih-item {
    border-color: #fc8686;
}

.calendar-day-item-text {
    user-select: none;
    height: 24px;
    line-height: 32px;
    font-size: 14px;
    width: 100%;
    color: #444461;
    text-align: center;
}

.calendar-day-itemactive {
    color: #fc8686 !important;
    font-weight: 600;
}

.calendar-day-itemgray {
    opacity: .6;
}

.calendar-week-head {
    width: 100%;
    height: 30px;
    display: flex;
    justify-content: space-between;
    box-sizing: border-box;
    padding: 0px 10px;
}

.calendar-week-head-event {
    font-size: 20px;
    width: 40px;
    text-align: center;
    height: 20px;
    line-height: 22px;
    margin: auto 0px;
    user-select: none;
    font-weight: 600;
}

.calendar-week-head-txt {
    font-size: 14px;
    height: 20px;
    line-height: 22px;
    margin: auto 0px;
}
</style>